package logic;

public class IdiotTour implements Tour{

	public static void main(String[] args) {
		IdiotTour ta = new IdiotTour();
		Vertex a = ta.tour[2];
		Vertex b = ta.tour[3];
		Vertex c = ta.tour[7];
		Vertex d = ta.tour[6];

		ta.print();
		
		System.out.println("Flip(" + a.index + ", " + b.index + ", " + c.index
				+ ", " + d.index + ")");
		ta.flip(a, b, c, d);
		ta.print();
	}
	
	Vertex[] tour;

	
	private IdiotTour() {
		Vertex s = new Vertex(0, 0, 5);
		Vertex t = new Vertex(0, 0, 3);
		Vertex a = new Vertex(0, 0, 1);
		Vertex b = new Vertex(0, 0, 0);
		Vertex v = new Vertex(0, 0, 4);
		Vertex u = new Vertex(0, 0, 6);
		Vertex d = new Vertex(0, 0, 7);
		Vertex c = new Vertex(0, 0, 2);
		Vertex[] temp = {s, t, a, b, v, u, d, c};
		tour = temp;
	}
	
	/*
	 * Copies from intarray tour and gets objects from Graph g
	 */
	public IdiotTour(int[] tour, Graph g){
		this.tour = new Vertex[tour.length];
		for(int i=0; i<tour.length ; i++){
			this.tour[i] = g.vertices[tour[i]];
		}
	}
	
	private void print() {
		System.out.print("Tour = [");
		for (int i = 0; i < tour.length - 1; i++) {
			System.out.print(tour[i].index + ", ");
		}
		System.out.println(tour[tour.length - 1].index+ "]");
	}

	public IdiotTour(Vertex[] tour, Graph g){
		this.tour = new Vertex[tour.length];
		for(int i=0; i<tour.length ; i++){
			this.tour[i] = tour[i];
		}
	}

	@Override
	public Vertex next(Vertex a) {
		for(int i=0; i<tour.length;i++){
			if(a==tour[i]){
				if(i==tour.length-1){
					return tour[0];
				}
				return tour[i+1];
			}
		}
		return null;
	}

//	@Override
//	public Vertex next(int index) {
//		if(index==tour.length-1){
//			return tour[0];
//		}
//		return tour[index+1];
//	}

	@Override
	public Vertex prev(Vertex a) {
		for(int i=0; i<tour.length;i++){
			if(a==tour[i]){
				if(i==0){
					return tour[tour.length-1];
				}
				return tour[i-1];
			}
		}
		return null;
	}

//	@Override
//	public Vertex prev(int index) {
//		if(index==0){
//			return tour[tour.length-1];
//		}
//		return tour[index-1];
//	}

	@Override
	public void flip(Vertex a, Vertex b, Vertex c, Vertex d) {
		int indexa = -1;
		int indexb = -1;
		int indexc = -1;
		int indexd = -1;
		for(int i=0; i<tour.length;i++){
			if(tour[i]==a){
				indexa = i;
			}
			if(tour[i]==b){
				indexb = i;
			}
			if(tour[i]==c){
				indexc = i;
			}
			if(tour[i]==d){
				indexd = i;
			}
		}
		flip(indexa,indexb,indexc,indexd);
	}


	private void flip(int a, int b, int c, int d) {
		// Reverse a to c (or c to a)
		int growingindex = b;
		int shrinkingindex = d;
		//              if(a>c){
			//                      smallindex = c;
			//                      bigindex = a;
			//              }
		while(shrinkingindex!=growingindex && 
				!(shrinkingindex==growingindex-1)){
			//Make the switch
			Vertex temp = tour[growingindex];
			tour[growingindex] = tour[shrinkingindex];
			tour[shrinkingindex] = temp;
			//update variables
			growingindex += 1;
			shrinkingindex -= 1;
			//follow tour cycle after start and end index
			if(growingindex>tour.length-1){
				growingindex = 0;
			}
			if(shrinkingindex<0){
				shrinkingindex = tour.length-1;
			}
		}

		//              // Set b -> c and a -> d
		//              Vertex temp = tour[a];
		//              tour[a] = tour[c];
		//              tour[c] = temp;
	}

	public String toString(){
		StringBuilder sb = new StringBuilder();
		for(int i=0 ; i<tour.length ; i++){
			sb.append(tour[i].index);
			if(i<tour.length-1){
				sb.append('\n');
			}
		}
		return sb.toString();
	}

	@Override
	public int size() {
		return tour.length;
	}

	@Override
	public Vertex getCity(int index) {
		return tour[index];
	}

	@Override
	public Vertex[] getTour() {
		return tour;
	}

	@Override
	public int length() {
		int distance = 0;
		for(int i=0;i<tour.length; i++){
			if(i==tour.length-1){
				distance += tour[i].getEuclideanDistance(tour[0]);
			} else {
				distance += tour[i].getEuclideanDistance(tour[i+1]);
			}
		}
		return distance;
	}


	@Override
	public boolean between(Vertex a, Vertex b, Vertex c) {
		Vertex temp;
		while((temp = next(a))!=c){
			if(temp==b){
				return true;
			}
		}
		return false;
	}

}
